package StudyCode.Component;

import java.awt.*;
import java.beans.BeanInfo;
import java.beans.EventSetDescriptor;
import java.beans.Introspector;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author lixiaoyao
 */
public class EventTracer {

	private InvocationHandler invocationHandler;

	public EventTracer() {
		// the handler for all event proxies
		this.invocationHandler = new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				System.out.println(method + ":" + args[0]);
				return null;
			}
		};
	}

	/**
	 * Adds event tracers for all events to which this component and its children can listen
	 */

	public void add(Component component) {
		try {
			// get all events to which this component can listen
			BeanInfo beanInfo = Introspector.getBeanInfo(component.getClass());

			EventSetDescriptor[] eventSetDescriptors = beanInfo.getEventSetDescriptors();
			for (EventSetDescriptor eventSetDescriptor : eventSetDescriptors) {
				addListener(component, eventSetDescriptor);
			}
		} catch (Exception ex) {

		}

		// ok not to add listeners if exception is thrown

		if (component instanceof Container) {
			// get all children and call add recursively
			for (Component component1 : ((Container) component).getComponents()) {
				add(component1);
			}
		}

	}

	/**
	 *
	 */
	public void addListener(Component component, EventSetDescriptor eventSetDescriptor) {
		// make proxy object for this listener type and route all calls to the handler
		Object proxy = Proxy.newProxyInstance(null, new Class[]{eventSetDescriptor.getListenerType()}, invocationHandler);

		// add the proxy as a listener to the component
		Method addListenerMethod = eventSetDescriptor.getAddListenerMethod();
		try {
			addListenerMethod.invoke(component, proxy);
		} catch (ReflectiveOperationException ex) {
			//
		}
		// ok not to add listener if exception is thrown
	}

	public static void main(String[] args) {
		EventTracer tracer = new EventTracer();
		tracer.add(new ColorChooserFrame());
	}

}
